package com.spit.hkpost.viewmodel

import android.os.Build
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.databinding.ObservableBoolean
import androidx.lifecycle.MutableLiveData
import com.blankj.utilcode.util.LogUtils
import com.blankj.utilcode.util.ToastUtils
import com.gg.reader.api.dal.GClient
import com.gg.reader.api.dal.HandlerDebugLog
import com.gg.reader.api.dal.HandlerTagEpcLog
import com.gg.reader.api.dal.HandlerTagEpcOver
import com.gg.reader.api.protocol.gx.EnumG
import com.gg.reader.api.protocol.gx.LogBaseEpcInfo
import com.gg.reader.api.protocol.gx.MsgAppGetBaseVersion
import com.gg.reader.api.protocol.gx.MsgBaseInventoryEpc
import com.gg.reader.api.protocol.gx.MsgBaseSetBaseband
import com.gg.reader.api.protocol.gx.MsgBaseSetPower
import com.gg.reader.api.protocol.gx.MsgBaseStop
import com.gg.reader.api.protocol.gx.ParamEpcFilter
import com.gg.reader.api.protocol.gx.ParamEpcReadTid
import com.gg.reader.api.utils.StringUtils
import com.spit.hkpost.bean.AppRoomDataBase
import com.spit.hkpost.bean.RfidStateBean
import com.spit.hkpost.keyctrl.GlobalClient
import com.spit.hkpost.keyctrl.InventoryInfo
import com.spit.hkpost.keyctrl.TagInfo
import com.spit.hkpost.service.PowerUtil
import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel
import me.hgj.jetpackmvvm.callback.databind.BooleanObservableField
import me.hgj.jetpackmvvm.callback.databind.IntObservableField
import me.hgj.jetpackmvvm.callback.databind.StringObservableField
import java.util.Date
import java.util.Hashtable
import java.util.Timer
import java.util.TimerTask

/**
 * @Author nike
 * @Date 2023/7/24 15:06
 * @Description
 */
class RfidModel : BaseViewModel() {

    var rfidData: MutableLiveData<InventoryInfo> = MutableLiveData()

    var isOpen: MutableLiveData<Boolean> = MutableLiveData()

    var longPressNext = BooleanObservableField()

    var KEYCODE_MEDIA_NEXT = IntObservableField(619)

    var isSearchOpen: MutableLiveData<String> = MutableLiveData()

    var language: MutableLiveData<Int> = MutableLiveData()

    val configDao = AppRoomDataBase.get().getConfigDao()

    var epcData: MutableLiveData<RfidStateBean> = MutableLiveData()

    var scanData: MutableLiveData<RfidStateBean> = MutableLiveData()

    var epcSearchData: MutableLiveData<RfidStateBean> = MutableLiveData()

    var client: GClient = GlobalClient.getClient()

    var tagFindParam: String? = null

    private var timer: Timer? = null
    private var time: Long = 0
    private var speed = 0

    private val tagMap = LinkedHashMap<String, TagInfo>()
    var isScan = BooleanObservableField(false)

     fun readTimer() {
        if (timer != null) {
            timer!!.cancel()
            timer = null
        }
        timer = Timer()
        timer!!.schedule(object : TimerTask() {
            @RequiresApi(api = Build.VERSION_CODES.N)
            override fun run() {
                time += 10
                handler.sendEmptyMessage(2)
                if (time % 1000 == 0L) {
                    synchronized(tagMap) {
                        val sum: Int = tagMap.values.stream().mapToInt(TagInfo::getCount).sum()
                        val rate: Int = sum - speed
                        speed = sum
                        handler.sendMessage(handler.obtainMessage(3, rate, 0))
                    }
                }
            }
        }, 0, 10)
    }
    var handler: Handler = object : Handler(Looper.getMainLooper()) {
        override fun handleMessage(msg: Message) {
            when (msg.what) {
//                0 -> LogUtils.e(tagMap.size)
//                1 -> LogUtils.e(tagList.size)
//                2 -> LogUtils.e(time.toString() + "ms")
//                3 -> LogUtils.e(msg.arg1.toString() + "t/s")
            }
            super.handleMessage(msg)
        }
    }

    fun config(){
        var configBean = configDao.findFirst()
        val msgBaseSetPower = MsgBaseSetPower()
        val hashtable = Hashtable<Int, Int>()
        hashtable[1] = configBean.power
        msgBaseSetPower.dicPower = hashtable
        client.sendSynMsg(msgBaseSetPower)
        if (!msgBaseSetPower.rtMsg.contains("Success")){
            LogUtils.e("天线功率设置失败")
        }

        val msgBaseSetBaseband = MsgBaseSetBaseband()
        //基带速度 1密集 3快速
        msgBaseSetBaseband.setBaseSpeed(1)
        // session 0123
        msgBaseSetBaseband.setSession(0)
        //Q值  单0  多4
        msgBaseSetBaseband.setqValue(if (configBean.session == 0) 0 else 4)
        //盘存方式 0A 1B 2AB
        msgBaseSetBaseband.setInventoryFlag(2)
        client.sendSynMsg(msgBaseSetBaseband)
        if (!msgBaseSetBaseband.rtMsg.contains("Success")){
            LogUtils.e("标签模式设置失败")
        }
    }

    var initConn = object : ObservableBoolean(){
        override fun get(): Boolean {
            PowerUtil.power("1")
            val baudRateList = intArrayOf(460800, 115200)
            for (i in baudRateList) {
                val b: Boolean = return if(openReader(i.toString() + "")){
                    config()

                    val getBaseVersion = MsgAppGetBaseVersion()
                    client.sendSynMsg(getBaseVersion)
                    LogUtils.e(
                        "RFID模块连接成功",
                        getBaseVersion.baseVersions
                    )

                    true
                }else{
                    LogUtils.e("RFID模块连接失败")
                    false
                }
                if (b) {
                    break
                }
            }
            return false
        }
    }

    private fun initRfid() {
        PowerUtil.power("1")
        val baudRateList = intArrayOf(460800, 115200)
        for (i in baudRateList) {
            val b: Boolean = openReader(i.toString() + "")
            if (b) {
                break
            }
        }
    }

    private fun openReader(baudRate: String): Boolean {
        if (client.openAndroidSerial("/dev/ttyS3:$baudRate", 0)) {
            val stop = MsgBaseStop()
            client.sendSynMsg(stop)
            if (stop.rtCode == 0.toByte()) {
                return true
            } else {
                client.close()
                return false
            }
        } else {
            ToastUtils.showShort("打開串口失敗")
        }
        return false
    }

    fun onTagCallback(){
        client.onTagEpcLog = HandlerTagEpcLog { s, logBaseEpcInfo ->
            if (logBaseEpcInfo.result == 0) {
//                synchronized(tagMap) {
//                    processTag(logBaseEpcInfo)
//                }
                var info = InventoryInfo()
                info.TagId = logBaseEpcInfo.epc
                info.Rssi = logBaseEpcInfo.rssi.toString()
                if (!info.TagId.isNullOrEmpty()){
                    rfidData.postValue(info)
                }
//                LogUtils.e(logBaseEpcInfo.epc)
            }
        }
        client.onTagEpcOver = HandlerTagEpcOver { s, logBaseEpcOver ->
            Log.e("LogBaseEpcOver", logBaseEpcOver.rtMsg)
            handler.sendEmptyMessage(1)
        }
        client.debugLog = object : HandlerDebugLog() {
            override fun sendDebugLog(s: String) {
                Log.e("sendDebugLog", s)
            }

            override fun receiveDebugLog(s: String) {
                Log.e("receiveDebugLog", s)
            }

            override fun crcErrorLog(s: String) {
                Log.e("crcErrorLog", s)
            }
        }
    }

    private fun processTag(logBaseEpcInfo: LogBaseEpcInfo) {
        val key = logBaseEpcInfo.epc + logBaseEpcInfo.tid
        if (tagMap.containsKey(key)) {
            val tagInfo = tagMap[key]
            tagInfo!!.count = tagInfo.count + 1
        } else {
            val tagInfo = TagInfo()
            tagInfo.index = tagMap.size + 1
            tagInfo.type = "6C"
            tagInfo.isErrorTag = logBaseEpcInfo.result != 0
            tagInfo.epc = logBaseEpcInfo.epc
            tagInfo.tid = logBaseEpcInfo.tid
            tagInfo.userData = logBaseEpcInfo.userdata
            tagInfo.reserved = logBaseEpcInfo.reserved
            tagInfo.count = 1
            tagInfo.readTime = Date()
            tagInfo.rssi = logBaseEpcInfo.rssi.toString()
            tagMap[key] = tagInfo
        }
        handler.sendEmptyMessage(0)
    }

    fun onStart(content: String?){
        client.sendUnsynMsg(MsgBaseStop())
        val msg = MsgBaseInventoryEpc()
        msg.antennaEnable = EnumG.AntennaNo_1
        msg.inventoryMode = EnumG.InventoryMode_Inventory
        //TID  mode 0自适应 1定长   len默认6
        msg.readTid = ParamEpcReadTid(0, 6)

        //是否匹配 0无 1EPC 2TID 3用户区
        var area = 1
        if (area != 0 && !StringUtils.isNullOfEmpty(content)) {
            tagFindParam = content
            val filter = ParamEpcFilter()
            filter.area = area
            filter.bitStart = if (area == 1) 32 else 0
            filter.bitLength = content!!.length * 4
            filter.hexData = content
            msg.filter = filter
        }
        client.sendSynMsg(msg)
        if (msg.rtCode.toInt() == 0) {
            readTimer()
        }
        onTagCallback()
    }

    fun onClose(){
        tagFindParam = null
        val stop = MsgBaseStop()
        client.sendSynMsg(stop)
        if (timer != null) {
            timer!!.cancel()
            timer = null
        }
//        PowerUtil.power("0")
        if (client != null){
//            client.close()
        }
        LogUtils.e("断开连接")
    }


}